package com.alibaba.citrus.cr.forecast.functions.forecastorder.ability;

import com.alibaba.acm.shaded.com.google.common.collect.Lists;
import com.alibaba.citrus.cr.common.annotation.FunctionInvoker;
import com.alibaba.citrus.cr.forecast.common.DateUtils;
import com.alibaba.citrus.cr.forecast.functions.forecastorder.constants.ForecastConstants;
import com.alibaba.citrus.cr.forecast.repository.ForecastOrderQueryRepository;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.SalesPlanLineQueryService;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.SalesPlanQueryService;
import com.alibaba.citrus.cr.sales.plan.api.statistics.SalesPlanCustomerStatQueryService;
import com.alibaba.citrus.cr.sales.plan.api.statistics.SalesPlanScItemStatQueryService;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQueryPlanLineRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQueryPlanScItemStatRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQuerySalePlanRequest;
import com.alibaba.citrus.cr.sales.plan.model.enums.ContractStatDimensionEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesStatBizTypeEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.StatPoolTypeEnum;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanStatScItemSDO;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.esdegrade.dto.GetEsDegradeValueResponse;
import com.epoch.app.bcorder.esdegrade.service.EsDegradeService;
import com.epoch.app.bcorder.model.dto.MonthContractAndRollingCountResponse;
import com.epoch.app.bcorder.model.dto.QueryQuantityListByAddressAndScItemRequest;
import com.epoch.app.bcorder.model.dto.QueryQuantityListByAddressAndScItemResponse;
import com.epoch.app.bcorder.service.SalesPlanService;
import com.epoch.app.crb2btradecenter.api.orderlinequery.service.OrderLineQueryService;
import com.epoch.app.crb2btradecenter.model.dto.CountOrderNumberResponse;
import com.epoch.app.crb2btradecenter.model.dto.CountSaleOrderForReportRequest;
import com.epoch.app.crb2btradecenter.model.dto.CountSaleOrderForReportResponse;
import com.epoch.app.crb2btradecenter.model.dto.PageQueryOrderLineESListRequest;
import com.epoch.app.crb2btradecenter.service.CrB2bTradeCenterService;
import com.epoch.app.crforecastsales.enums.AnalyzeReasonsSEO;
import com.epoch.app.crforecastsales.sdo.ForecastOrderLineSDO;
import com.epoch.app.crforecastsales.sdo.ForecastOrderSDO;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.api.strategyquery.service.StrategyQueryService;
import com.epoch.app.crplatformenhance.dto.request.IdQueryRequest;
import com.epoch.app.crplatformenhance.enums.StrategyTypeEnum;
import com.epoch.app.crplatformenhance.model.dto.StrategyPageQueryRequest;
import com.epoch.app.crplatformenhance.model.dto.StrategyPageQueryResponse;
import com.epoch.app.crplatformenhance.model.dto.StrategyQueryByIdRequest;
import com.epoch.app.crplatformenhance.model.dto.StrategyQueryByIdResponse;
import com.epoch.app.crplatformenhance.model.enums.ProportionTypeEnum;
import com.epoch.app.crplatformenhance.sdo.DimensionSDO;
import com.epoch.app.crplatformenhance.sdo.OrganizationSDO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author yuanDeng  策略计算
 * @Date 2021/10/27 16:51
 **/
@Service
@Primary
public class StrategyCalculate {
    @Autowired
    SalesPlanCustomerStatQueryService salesPlanCustomerStatRepository;
    @Autowired
    SalesPlanScItemStatQueryService salesPlanScItemStatQueryService;
    @Autowired
    SalesPlanQueryService salesPlanQueryService;
    @Autowired
    SalesPlanLineQueryService salesPlanLineQueryService;
    @Autowired
    StrategyQueryService strategyQueryService;
    @Autowired
    ForecastOrderQueryRepository forecastOrderQueryRepository;
    @Autowired
    OrganizationQueryService organizationQueryService;
    @Autowired
    OrderLineQueryService orderLineQueryService;
    @Autowired
    SalesPlanService salesPlanService;
    @Autowired
    CrB2bTradeCenterService crB2bTradeCenterService;
    @Resource
    EsDegradeService esDegradeService;

    private static Log log = Log.getLogger(StrategyCalculate.class);
    private Map<String, ForecastOrderSDO> FORE_CAST_ORDER_MAP = new HashMap<>();

//    private Integer PARENT_ID;


    /**
     * 、
     * 这个接口需要的数据     1公司组织编码 （查询策略，查询月度计划planId） 2  订单行id 客户地址 货品id  组织  部门  渠道  量值  比例
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> allocationProportionDepartment(List<ForecastOrderLineSDO> forecastOrderLineSDOS) {
        if (null == forecastOrderLineSDOS) {
            return null;
        }
        for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
            log.error("查询预报主单id" + forecastOrderLineSDO.getMainOrderId());
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            log.error("查询预报主单结果" + JSONObject.toJSONString(load));
            FORE_CAST_ORDER_MAP.put(forecastOrderLineSDO.getMainOrderId(), load);
        }
        //选择的都是同一个组织下面的订单
        ForecastOrderSDO load = FORE_CAST_ORDER_MAP.get(forecastOrderLineSDOS.get(0).getMainOrderId());
        if (null == load) {
            return null;
        }


        log.error("查询planId入参" + load.getOrganizationCode());
        String planId = queryParentId(load.getOrganizationCode());
        log.error("查询planId结果" + planId);
        if (StringUtils.isBlank(planId)) {
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                forecastOrderLineSDO.setAnalysisReason(AnalyzeReasonsSEO.MONTHLY_PLAN.getName());
                Map<String, Object> features = forecastOrderLineSDO.getFeatures();
                if (MapUtils.isEmpty(features)) {
                    features = new HashMap<>();
                }
                features.put(ForecastConstants.BULB_TYPE, AnalyzeReasonsSEO.MONTHLY_PLAN.getBulbType());
                forecastOrderLineSDO.setPredictReplyAmount(0);
                forecastOrderLineSDO.setAnalysisTime(new Date());
            }
            return forecastOrderLineSDOS;
        }
        log.error("查询策略入参" + load.getOrganizationCode());
        DimensionSDO dimensionSDO = strategyType(load.getOrganizationCode());
        log.error("查询策略出参" + JSONObject.toJSONString(dimensionSDO));
        //DimensionSDO dimensionSDO = strategyType("297563628604702724");
        //没有策略或者策略过期了
        if (Objects.isNull(dimensionSDO)) {
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                forecastOrderLineSDO.setAnalysisReason(AnalyzeReasonsSEO.COMPUTING_STRATEGY.getName());
                Map<String, Object> features = forecastOrderLineSDO.getFeatures();
                if (MapUtils.isEmpty(features)) {
                    features = new HashMap<>();
                }
                features.put(ForecastConstants.BULB_TYPE, AnalyzeReasonsSEO.COMPUTING_STRATEGY.getBulbType());
                forecastOrderLineSDO.setPredictReplyAmount(0);
                forecastOrderLineSDO.setAnalysisTime(new Date());
            }
            return forecastOrderLineSDOS;
        }

        /*switch (dimensionSDO.getRuleValue()){

        }*/
        if (Objects.equals(dimensionSDO.getRuleValue(), "1")) {
            log.error("根据部门查询月度计划入参+deltaAmountDepartment" + planId + JSONObject.toJSONString(forecastOrderLineSDOS));
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = deltaAmountDepartment(planId, forecastOrderLineSDOS);
            log.error("根据部门查询月度计划出参+deltaAmountDepartment" + JSONObject.toJSONString(forecastOrderLineSDOS1));
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "2")) {
            log.error("根据部门查询月度计划入参+planningAmountDepartment" + planId + JSONObject.toJSONString(forecastOrderLineSDOS));
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = planningAmountDepartment(planId, forecastOrderLineSDOS);
            log.error("根据部门查询月度计划出参+planningAmountDepartment" + JSONObject.toJSONString(forecastOrderLineSDOS1));
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.PLAN_RATIO.getCode()));//计算好比例最终赋值给lastRatio ，前台可以直接获取lastRatio的值
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "3")) {//预算占比
            log.error("根据部门查询月度计划入参" + planId + JSONObject.toJSONString(forecastOrderLineSDOS));
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = budgetAmountDepartment(planId, forecastOrderLineSDOS);
            log.error("根据部门查询月度计划出参" + JSONObject.toJSONString(forecastOrderLineSDOS1));
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.BUDGET_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "4")) {
            log.error("根据部门查询月度计划入参quotaAmountDepartment" + planId + JSONObject.toJSONString(forecastOrderLineSDOS));
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = quotaAmountDepartment(planId, forecastOrderLineSDOS);
            log.error("根据部门查询月度计划出参quotaAmountDepartment" + JSONObject.toJSONString(forecastOrderLineSDOS1));
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.TASK_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "5")) {
            log.error("根据部门查询综合占比comprehensiveAmountDepartment" + planId + JSONObject.toJSONString(forecastOrderLineSDOS));
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = comprehensiveAmountDepartment(planId, forecastOrderLineSDOS, dimensionSDO.getDetails());
            log.error("根据部门查询月度计划出参comprehensiveAmountDepartment" + JSONObject.toJSONString(forecastOrderLineSDOS1));
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.WHOLE_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        return forecastOrderLineSDOS;
    }

    /**
     * 、
     * 这个接口需要的数据     1公司组织编码 （查询策略，查询月度计划planId） 2  订单行id 客户地址 货品id  组织  部门  渠道  量值  比例
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> allocationProportionChannel(List<ForecastOrderLineSDO> forecastOrderLineSDOS) {
        for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            FORE_CAST_ORDER_MAP.put(forecastOrderLineSDO.getMainOrderId(), load);
        }
        //选择的都是同一个组织下面的订单
        ForecastOrderSDO load = FORE_CAST_ORDER_MAP.get(forecastOrderLineSDOS.get(0).getMainOrderId());
        if (null == load) {
            return null;
        }

        String planId = queryParentId(load.getOrganizationCode());
        if (StringUtils.isBlank(planId)) {
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                forecastOrderLineSDO.setAnalysisReason(AnalyzeReasonsSEO.MONTHLY_PLAN.getName());
                Map<String, Object> features = forecastOrderLineSDO.getFeatures();
                if (MapUtils.isEmpty(features)) {
                    features = new HashMap<>();
                }
                features.put(ForecastConstants.BULB_TYPE, AnalyzeReasonsSEO.MONTHLY_PLAN.getBulbType());
                forecastOrderLineSDO.setPredictReplyAmount(0);
                forecastOrderLineSDO.setAnalysisTime(new Date());
            }
            return forecastOrderLineSDOS;
        }
        DimensionSDO dimensionSDO = strategyType(load.getOrganizationCode());
        //没有策略或者策略过期了
        if (Objects.isNull(dimensionSDO)) {
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                forecastOrderLineSDO.setAnalysisReason(AnalyzeReasonsSEO.COMPUTING_STRATEGY.getName());
                Map<String, Object> features = forecastOrderLineSDO.getFeatures();
                if (MapUtils.isEmpty(features)) {
                    features = new HashMap<>();
                }
                features.put(ForecastConstants.BULB_TYPE, AnalyzeReasonsSEO.COMPUTING_STRATEGY.getBulbType());
                forecastOrderLineSDO.setPredictReplyAmount(0);
                forecastOrderLineSDO.setAnalysisTime(new Date());
            }
            return forecastOrderLineSDOS;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "1")) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = deltaAmountChannel(planId, forecastOrderLineSDOS);
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "2")) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = planningAmountChannel(planId, forecastOrderLineSDOS);
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.PLAN_RATIO.getCode()));//计算好比例最终赋值给lastRatio ，前台可以直接获取lastRatio的值
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "3")) {//预算占比
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = budgetAmountChannel(planId, forecastOrderLineSDOS);
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.BUDGET_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "4")) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = quotaAmountChannel(planId, forecastOrderLineSDOS);
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.TASK_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        if (Objects.equals(dimensionSDO.getRuleValue(), "5")) {
            List<ForecastOrderLineSDO> forecastOrderLineSDOS1 = comprehensiveAmountChannel(planId, forecastOrderLineSDOS, dimensionSDO.getDetails());
            List<ForecastOrderLineSDO> lastRatio = Nullable.stream(forecastOrderLineSDOS1).map(it -> {
                it.getFeatures().put(ForecastConstants.LAST_RATIO, it.getFeatures().get(ProportionTypeEnum.WHOLE_RATIO.getCode()));
                return it;
            }).collect(Collectors.toList());
            return lastRatio;
        }
        return forecastOrderLineSDOS;
    }

    /**
     * 根据组织获取策略类型
     */
    @FunctionInvoker
    public DimensionSDO strategyType(String organizationCode) {
        /**
         *   1  差量占比  2  计划量占比   3 任务量占比 4   5 综合占比*/
        StrategyPageQueryRequest strategyPageQueryRequest = new StrategyPageQueryRequest();

        strategyPageQueryRequest.setOrganizationCode(organizationCode);
        //strategyPageQueryRequest.setStatus(1);
        strategyPageQueryRequest.setType(StrategyTypeEnum.REPLY_COMPUTE.getCode());
        //strategyPageQueryRequest.setStrategyName(StrategyTypeEnum.REPLY_COMPUTE.name());//应该输入策略类型4
        log.info("查询回复计算策略接口入参" + JSONObject.toJSONString(strategyPageQueryRequest));
        Result<List<StrategyPageQueryResponse>> listResult = strategyQueryService.pageQuery(strategyPageQueryRequest);
        log.info("查询回复计算策略接口出参" + JSONObject.toJSONString(listResult));
        if (Objects.nonNull(listResult) && CollectionUtils.isNotEmpty(listResult.getResult())) {
            StrategyPageQueryResponse strategyPageQueryResponse = listResult.getResult().get(0);
            Date date = new Date();
            if (strategyPageQueryResponse.getValidBeginTime().getTime() <= date.getTime() && strategyPageQueryResponse.getValidEndTime().getTime() >= date.getTime()) {
                StrategyQueryByIdRequest strategyQueryByIdRequest = new StrategyQueryByIdRequest();
                strategyQueryByIdRequest.setId(strategyPageQueryResponse.getId());
                log.info("查询回复计算策略第二步接口入参" + JSONObject.toJSONString(strategyQueryByIdRequest));
                Result<StrategyQueryByIdResponse> strategyQueryByIdResponseResult = strategyQueryService.queryById(strategyQueryByIdRequest);
                log.info("查询回复计算策略第二步接口出参" + JSONObject.toJSONString(strategyQueryByIdResponseResult));
                if (null == strategyQueryByIdResponseResult || null == strategyQueryByIdResponseResult.getResult()
                        || null == strategyQueryByIdResponseResult.getResult().getStrategySDO()) {
                    return null;
                }

                List<DimensionSDO> dimensionSDOList = strategyQueryByIdResponseResult.getResult().getStrategySDO().getDimensionSDOList();
                if (CollectionUtils.isNotEmpty(dimensionSDOList)) {
                    DimensionSDO dimensionSDO = dimensionSDOList.get(0);
                    return dimensionSDO;
                }
                return null;
            }
        }

        return null;
    }


    /**
     * 根据组织 部门 渠道 客户查询 差量  1  部门差量占比  todo  计划减去销售订单已经发货订单（差量占比需要重新查询）
     * 部门
     *
     * @param list
     * @return
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> deltaAmountDepartment(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> tempLineList = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getDepartmentCode())) {
                //查询部门月度计划
                SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageQueryPlanScItemListDepartmentCode(planId, forecastOrderLineSDO);
                if ((Objects.nonNull(salesPlanStatScItemSDO))) {
                    //根据部门查询改部门这个月有多少
                    // PageQueryOrderLineESListRequest pageQueryOrderLineESListRequest = new PageQueryOrderLineESListRequest();
                    //pageQueryOrderLineESListRequest.setSaleDepartment(Lists.newArrayList(load.getDepartmentCode()));
                    //需要查询什么状态的销售订单的
                    // pageQueryOrderLineESListRequest.setGoodsId(forecastOrderLineSDO.getScItemId());
                    // pageQueryOrderLineESListRequest.setOrderSubStatus("4");
                    // Result<CountOrderNumberResponse> countOrderNumberResponseResult = orderLineQueryService.countOrderNumber(pageQueryOrderLineESListRequest);

                    //todo 时间范围是当月还是什么时间段的计划量
                    CountSaleOrderForReportRequest countSaleOrderForReportRequest = new CountSaleOrderForReportRequest();
                    countSaleOrderForReportRequest.setGmtCreateStartTime(DateUtils.firstDayOfMonth());
                    countSaleOrderForReportRequest.setGmtCreateEndTime(DateUtils.endDayOfMonth());
                    countSaleOrderForReportRequest.setDetailStatusList(Arrays.asList(3, 4));
                    countSaleOrderForReportRequest.setDepartmentCodes(Arrays.asList(load.getDepartmentCode()));
                    countSaleOrderForReportRequest.setScItemId(forecastOrderLineSDO.getScItemId());
                    CountSaleOrderForReportResponse countSaleOrderForReportResponse = crB2bTradeCenterService.countSaleOrderForReport(countSaleOrderForReportRequest);

                    //计划量和发货数量的差量
                    Integer l = salesPlanStatScItemSDO.getTaskCount();
                    if (Objects.nonNull(countSaleOrderForReportResponse)) {
                        l = (salesPlanStatScItemSDO.getTaskCount() - (int) Float.parseFloat(countSaleOrderForReportResponse.getDeliveryAmount()));
                    }
                    //差量小于等于0就是0呗
                    if (l < 0) {
                        l = 0;
                    }
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.DELTA, l.toString());
                    tempLineList.add(forecastOrderLineSDO);
                }
            }
        }
        int number = Nullable.stream(tempLineList).mapToInt(it -> (Objects.nonNull(it.getFeatures().get(ForecastConstants.DELTA)) ? Integer.parseInt(it.getFeatures().get(ForecastConstants.DELTA).toString()) : 0)).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(tempLineList).map(it -> {
            if (number == 0 || Integer.parseInt(it.getFeatures().get(ForecastConstants.DELTA).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.DIFFERENCE_RATIO.getCode(), Float.toString(0));
            } else {
                float diffFloat = Float.parseFloat(String.valueOf(it.getFeatures().get(ForecastConstants.DELTA))) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.DIFFERENCE_RATIO.getCode(), Float.toString(diffFloat));
            }
            return it;
        }).collect(Collectors.toList());

        return collect;
    }

    /**
     * 根据组织 部门 渠道 客户查询 差量  1  渠道差量占比  todo  计划减去销售订单已经发货订单（差量占比需要重新查询）
     * 渠道
     *
     * @param list
     * @return
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> deltaAmountChannel(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getSaleChannelCode())) {
                //查询渠道月度计划
                SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageQueryPlanScItemListGetChannelCode(planId, forecastOrderLineSDO);
                if ((Objects.nonNull(salesPlanStatScItemSDO))) {

                    CountSaleOrderForReportRequest countSaleOrderForReportRequest = new CountSaleOrderForReportRequest();
                    countSaleOrderForReportRequest.setGmtCreateStartTime(DateUtils.firstDayOfMonth());
                    countSaleOrderForReportRequest.setGmtCreateEndTime(DateUtils.endDayOfMonth());
                    countSaleOrderForReportRequest.setDetailStatusList(Arrays.asList(3, 4));
                    countSaleOrderForReportRequest.setChannelCodes(Arrays.asList(load.getSaleChannelCode()));
                    countSaleOrderForReportRequest.setScItemId(forecastOrderLineSDO.getScItemId());
                    CountSaleOrderForReportResponse countSaleOrderForReportResponse = crB2bTradeCenterService.countSaleOrderForReport(countSaleOrderForReportRequest);

                    Integer l = salesPlanStatScItemSDO.getTaskCount();
                    if (Objects.nonNull(countSaleOrderForReportResponse)) {
                        //任务量和发货数量的差量
                        l = salesPlanStatScItemSDO.getTaskCount() - (int) Float.parseFloat(countSaleOrderForReportResponse.getDeliveryAmount());
                    }
                    //差量小于等于0就是0呗
                    if (l < 0) {
                        l = 0;
                    }
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.DELTA, l.toString());
                    list1.add(forecastOrderLineSDO);
                }
            }
        }
        int number = Nullable.stream(list1).mapToInt(it -> Integer.parseInt(it.getFeatures().get(ForecastConstants.DELTA).toString())).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Integer.parseInt(it.getFeatures().get(ForecastConstants.DELTA).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.DIFFERENCE_RATIO.getCode(), Float.toString(0));
            } else {
                float number1 = Integer.parseInt(it.getFeatures().get(ForecastConstants.DELTA).toString()) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.DIFFERENCE_RATIO.getCode(), Float.toString(number1));
            }
            return it;
        }).collect(Collectors.toList());

        return collect;
    }

    /**
     * 2  计划量占比  部门
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> planningAmountDepartment(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getDepartmentCode())) {
                SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageQueryPlanScItemListDepartmentCode(planId, forecastOrderLineSDO);
                if ((Objects.nonNull(salesPlanStatScItemSDO))) {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.PLAN_AMOUNT, String.valueOf(salesPlanStatScItemSDO.getMonthCount()));

                } else {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.PLAN_AMOUNT, "0");
                }
                list1.add(forecastOrderLineSDO);
            }
        }
        int number = Nullable.stream(list1).mapToInt(it -> Objects.nonNull(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT)) ? Integer.parseInt(String.valueOf(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT))) : 0).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Integer.parseInt(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.PLAN_RATIO.getCode(), Float.toString(0));
            } else {
                float number1 = Integer.parseInt(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT).toString()) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.PLAN_RATIO.getCode(), Float.toString(number1));
            }
            return it;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 2  计划量占比  渠道
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> planningAmountChannel(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getSaleChannelCode())) {
                SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageQueryPlanScItemListGetChannelCode(planId, forecastOrderLineSDO);
                if ((Objects.nonNull(salesPlanStatScItemSDO))) {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.PLAN_AMOUNT, String.valueOf(salesPlanStatScItemSDO.getMonthCount()));

                } else {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.PLAN_AMOUNT, "0");
                }
                list1.add(forecastOrderLineSDO);
            }
        }
        int number = Nullable.stream(list1).mapToInt(it -> Objects.nonNull(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT)) ? Integer.parseInt(String.valueOf(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT))) : 0).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Integer.parseInt(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.PLAN_RATIO.getCode(), Float.toString(0));
            } else {
                float number1 = Integer.parseInt(it.getFeatures().get(ForecastConstants.PLAN_AMOUNT).toString()) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.PLAN_RATIO.getCode(), Float.toString(number1));
            }
            return it;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 3 任务量占比   部门
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> quotaAmountDepartment(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getDepartmentCode())) {
                SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageQueryPlanScItemListDepartmentCode(planId, forecastOrderLineSDO);
                if ((Objects.nonNull(salesPlanStatScItemSDO))) {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.QUOTA, salesPlanStatScItemSDO.getTaskCount().toString());
                    list1.add(forecastOrderLineSDO);
                    continue;
                }
            }

        }
        int number = Nullable.stream(list1).mapToInt(it -> Integer.parseInt(it.getFeatures().get(ForecastConstants.QUOTA).toString())).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Integer.parseInt(it.getFeatures().get(ForecastConstants.QUOTA).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.TASK_RATIO.getCode(), Float.toString(0));
                return it;
            } else {
                float number1 = Integer.parseInt(it.getFeatures().get(ForecastConstants.QUOTA).toString()) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.TASK_RATIO.getCode(), Float.toString(number1));
                return it;
            }
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 3 任务量占比   渠道
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> quotaAmountChannel(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = FORE_CAST_ORDER_MAP.get(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load) && StringUtils.isNotBlank(load.getSaleChannelCode())) {
                SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageQueryPlanScItemListGetChannelCode(planId, forecastOrderLineSDO);
                if ((Objects.nonNull(salesPlanStatScItemSDO))) {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.QUOTA, salesPlanStatScItemSDO.getTaskCount().toString());
                } else {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.QUOTA, "0");
                }
            }
            list1.add(forecastOrderLineSDO);
        }
        int number = Nullable.stream(list1).mapToInt(it -> Objects.nonNull(it.getFeatures().get(ForecastConstants.QUOTA)) ? Integer.parseInt(String.valueOf(it.getFeatures().get(ForecastConstants.QUOTA))) : 0).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Integer.parseInt(String.valueOf(it.getFeatures().get(ForecastConstants.QUOTA))) == 0) {
                it.getFeatures().put(ProportionTypeEnum.TASK_RATIO.getCode(), Float.toString(0));
            } else {
                float number1 = Integer.parseInt(it.getFeatures().get(ForecastConstants.QUOTA).toString()) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.TASK_RATIO.getCode(), Float.toString(number1));
            }
            return it;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 4 预算量占比   todo  新接口  部门
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> budgetAmountDepartment(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getDepartmentCode())) {
                MonthContractAndRollingCountResponse monthContract = searchContractNumberDepartment(forecastOrderLineSDO);
                if ((Objects.nonNull(monthContract))) {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.BUDGET_AMOUNT, monthContract.getMonthContractCount().toString());
                } else {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.BUDGET_AMOUNT, "0");
                }
                list1.add(forecastOrderLineSDO);
            }
        }
        int number = Nullable.stream(list1).mapToInt(it -> Objects.nonNull(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT)) ? Integer.parseInt(String.valueOf(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT))) : 0).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Objects.isNull(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT)) || Integer.parseInt(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.BUDGET_RATIO.getCode(), Float.toString(0));
            } else {
                float number1 = Float.parseFloat(String.valueOf(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT))) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.BUDGET_RATIO.getCode(), Float.toString(number1));
            }
            return it;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 4 预算量占比   todo  新接口  渠道
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> budgetAmountChannel(String planId, List<ForecastOrderLineSDO> list) {
        List<ForecastOrderLineSDO> list1 = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : list) {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load.getSaleChannelCode())) {
                MonthContractAndRollingCountResponse monthContract = searchContractNumberChannel(forecastOrderLineSDO);
                if ((Objects.nonNull(monthContract))) {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.BUDGET_AMOUNT, String.valueOf(monthContract.getMonthContractCount()));

                } else {
                    forecastOrderLineSDO.getFeatures().put(ForecastConstants.BUDGET_AMOUNT, "0");
                }
                list1.add(forecastOrderLineSDO);
            }
        }
        int number = Nullable.stream(list1).mapToInt(it -> Objects.nonNull(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT)) ? Integer.parseInt(String.valueOf(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT))) : 0).sum();
        List<ForecastOrderLineSDO> collect = Nullable.stream(list1).map(it -> {
            if (number == 0 || Integer.parseInt(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT).toString()) == 0) {
                it.getFeatures().put(ProportionTypeEnum.BUDGET_RATIO.getCode(), Float.toString(0));
            } else {
                float number1 = Float.parseFloat(String.valueOf(it.getFeatures().get(ForecastConstants.BUDGET_AMOUNT))) * 100 / number;
                it.getFeatures().put(ProportionTypeEnum.BUDGET_RATIO.getCode(), Float.toString(number1));
            }
            return it;
        }).collect(Collectors.toList());
        return collect;
    }


    /**
     * 5 综合占比 部门
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> comprehensiveAmountDepartment(String planId, List<ForecastOrderLineSDO> list, String s) {
        Map map1 = JSONObject.parseObject(s, Map.class);
        List<ForecastOrderLineSDO> maps = deltaAmountDepartment(planId, list);
        List<ForecastOrderLineSDO> maps1 = planningAmountDepartment(planId, maps);
        List<ForecastOrderLineSDO> maps2 = quotaAmountDepartment(planId, maps1);
        List<ForecastOrderLineSDO> maps3 = budgetAmountDepartment(planId, maps2);
        //根据id获取三个量占比
        List<ForecastOrderLineSDO> comprehensiveAmount = Nullable.stream(maps3).map(it -> {
            float deltaAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode())));
            float planningAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.PLAN_RATIO.getCode())));
            float quotaAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.BUDGET_RATIO.getCode())));
            float budgetAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.TASK_RATIO.getCode())));

            float l = (Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode()))) * deltaAmountPercentage
                    + Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.PLAN_RATIO.getCode()))) * planningAmountPercentage
                    + Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.BUDGET_RATIO.getCode()))) * quotaAmountPercentage
                    + Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.TASK_RATIO.getCode()))) * budgetAmountPercentage) / 100;
            if (MapUtils.isNotEmpty(it.getFeatures())) {
                it.getFeatures().put(ProportionTypeEnum.WHOLE_RATIO.getCode(), Float.toString(l));
            } else {
                it.setFeatures(new HashMap() {{
                    put(ProportionTypeEnum.WHOLE_RATIO.getCode(), Float.toString(l));
                }});
            }

            return it;
        }).collect(Collectors.toList());
        return comprehensiveAmount;
    }

    /**
     * 5 综合占比 渠道
     */
    @FunctionInvoker
    public List<ForecastOrderLineSDO> comprehensiveAmountChannel(String planId, List<ForecastOrderLineSDO> list, String s) {
        Map map1 = JSONObject.parseObject(s, Map.class);
        List<ForecastOrderLineSDO> maps = deltaAmountChannel(planId, list);
        List<ForecastOrderLineSDO> maps1 = planningAmountChannel(planId, maps);
        List<ForecastOrderLineSDO> maps2 = quotaAmountChannel(planId, maps1);
        List<ForecastOrderLineSDO> maps3 = budgetAmountChannel(planId, maps2);
        //根据id获取三个量占比
        List<ForecastOrderLineSDO> comprehensiveAmount = Nullable.stream(maps3).map(it -> {
            float deltaAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode())));
            float planningAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.PLAN_RATIO.getCode())));
            float quotaAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.BUDGET_RATIO.getCode())));
            float budgetAmountPercentage = Float.parseFloat(String.valueOf(it.getFeatures().get(ProportionTypeEnum.TASK_RATIO.getCode())));

            float l = (Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.DIFFERENCE_RATIO.getCode()))) * deltaAmountPercentage
                    + Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.PLAN_RATIO.getCode()))) * planningAmountPercentage
                    + Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.BUDGET_RATIO.getCode()))) * quotaAmountPercentage
                    + Integer.parseInt(String.valueOf(map1.get(ProportionTypeEnum.TASK_RATIO.getCode()))) * budgetAmountPercentage) / 100;

            it.getFeatures().put(ProportionTypeEnum.WHOLE_RATIO.getCode(), Float.toString(l));
            return it;
        }).collect(Collectors.toList());
        return comprehensiveAmount;
    }


    /**
     * 查询月度计划 月度计划的planId需要作为查询月度计划值的查询条件
     *
     * @param organizationCode
     * @return
     */

    @FunctionInvoker
    public String queryParentId(String organizationCode) {
        IdQueryRequest idQueryRequest = new IdQueryRequest();
        idQueryRequest.setType(104);
        //查询组织的上级分公司的id
        idQueryRequest.setId(organizationCode);
        log.info("查询月度计划planId第一步入参+getTopOrganizationList" + JSONObject.toJSONString(idQueryRequest));
        Result<List<OrganizationSDO>> topOrganizationList = organizationQueryService.getTopOrganizationList(idQueryRequest);
        log.info("查询月度计划planId第一步出参+getTopOrganizationList" + JSONObject.toJSONString(topOrganizationList));
        if (topOrganizationList.isSuccess() && !CollectionUtils.isEmpty(topOrganizationList.getResult())) {
            OrganizationSDO organizationSDO = topOrganizationList.getResult().get(topOrganizationList.getResult().size() - 1);

            PageQuerySalePlanRequest pageQuerySalePlanRequest = new PageQuerySalePlanRequest();
            Calendar cal = Calendar.getInstance();
            int year = cal.get(Calendar.YEAR);
            int month = cal.get(Calendar.MONTH) + 1;
            pageQuerySalePlanRequest.setPlanTime(year + "-" + month);//设置当前月份
            pageQuerySalePlanRequest.setOrgBusinessUnitCode(organizationSDO.getParentId());
            log.info("查询月度计划planId第二步入参+pageQuerySalesPlanList" + JSONObject.toJSONString(pageQuerySalePlanRequest));
            Result<PageResult<List<SalesPlanSDO>>> pageResultResult = salesPlanQueryService.pageQuerySalesPlanList(pageQuerySalePlanRequest);
            log.info("查询月度计划planId第二步出参+pageQuerySalesPlanList" + JSONObject.toJSONString(pageResultResult));
            if (pageResultResult != null && Objects.nonNull(pageResultResult.getResult()) && CollectionUtils.isNotEmpty(pageResultResult.getResult().getContent())) {
                String plantId = pageResultResult.getResult().getContent().get(0).getId().toString();
                return plantId;
            }
        }
        return null;

    }


    /**
     * 根据客户查询月度计划
     *
     * @param forecastOrderLineSDO
     * @return
     */
    @FunctionInvoker
    public SalesPlanLineSDO pageQuerySalesPlanLineList(String planId, ForecastOrderLineSDO forecastOrderLineSDO, ForecastOrderSDO forecastOrderSDO) {
        if (Objects.isNull(forecastOrderLineSDO)) {
            return null;
        }
//        ForecastOrderSDO forecastOrderSDO = null;
//        try {
//            forecastOrderSDO = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
//            if (Objects.isNull(forecastOrderSDO)) {
//                return null;
//            }
//        } catch (Exception e) {
////            e.printStackTrace();
//            log.error("ERROR:Query main order info in sales plan query failed:{}", e);
//            return null;
//        }

        // 客户地址+货品+planId  查询明细量
        PageQueryPlanLineRequest pageQueryPlanLineRequest = new PageQueryPlanLineRequest();
        pageQueryPlanLineRequest.setPlanId(planId);//
        //pageQueryPlanLineRequest.setCustomerAddress(forecastOrderSDO.getShipAddressInfo());
        pageQueryPlanLineRequest.setBizType(SalesStatBizTypeEnum.SALES_ORGANIZATION.getOrganizationType());
        pageQueryPlanLineRequest.setBizId(forecastOrderSDO.getOrganizationCode());
        pageQueryPlanLineRequest.setCustomerAddress(forecastOrderSDO.getReceiveAddressCode());
        pageQueryPlanLineRequest.setScItemId(forecastOrderLineSDO.getScItemId());//get("货品id")
        //pageQueryPlanLineRequest.setScItemId("285880564719391782");//get("货品id")
        log.info("客户查询月度计划入参" + JSONObject.toJSONString(pageQueryPlanLineRequest));
        try {
            //TODO 性能优化点 这里优化点可以切换为通过数据库查询明细而非ES，可以命中索引：planId + scItemId, 可以替换为com.alibaba.citrus.cr.sales.plan.repository.SalesPlanLineRepository.pageQuerySalesPlanLineList
            //支持es降级查询db
            GetEsDegradeValueResponse degradeValueResponse = esDegradeService.getEsDegradeValue();
            Result<PageResult<List<SalesPlanLineSDO>>> pageResultResult = null;
            if(Objects.nonNull(degradeValueResponse) && degradeValueResponse.getResult()){
                pageResultResult = salesPlanLineQueryService.pageQuerySalesPlanLineListFromDb(pageQueryPlanLineRequest);
            }else{
                pageResultResult = salesPlanLineQueryService.pageQuerySalesPlanLineList(pageQueryPlanLineRequest);
            }
            log.info("客户查询月度计划出参" + JSONObject.toJSONString(pageResultResult));
            if (Objects.nonNull(pageResultResult) &&
                    Objects.nonNull(pageResultResult.getResult()) &&
                    Objects.nonNull(pageResultResult.getResult().getContent()) &&
                    pageResultResult.getResult().getContent().size() > 0) {
                return pageResultResult.getResult().getContent().get(0);
            }
        } catch (Exception e) {
            log.error("ERROR:Query sales plan line list failed:{}", e);
//            e.printStackTrace();
        }

        return null;
    }

    /**
     * 根据部门查询月度计划 部门
     *
     * @param map
     * @return
     */
    @FunctionInvoker
    public SalesPlanStatScItemSDO pageQueryPlanScItemListDepartmentCode(String planId, ForecastOrderLineSDO map) {
        //渠道/ 部门 +货品+planId +pooltype（3）
        ForecastOrderSDO forecastOrderSDO = forecastOrderQueryRepository.load(map.getMainOrderId());
        PageQueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new PageQueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(planId);
        pageQueryPlanScItemStatRequest.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        pageQueryPlanScItemStatRequest.setScItemId(map.getScItemId());
        if (Objects.nonNull(forecastOrderSDO.getDepartmentCode())) {
            pageQueryPlanScItemStatRequest.setBizId(forecastOrderSDO.getDepartmentCode());
            pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getOrganizationType());
        }
        //部门
        log.error("部门查询月度计划入参" + JSONObject.toJSONString(pageQueryPlanScItemStatRequest));
        Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.pageQueryPlanScItemList(pageQueryPlanScItemStatRequest);
        log.error("部门查询月度计划出参" + JSONObject.toJSONString(pageResultResult));
        if (Objects.nonNull(pageResultResult.getResult()) && CollectionUtils.isNotEmpty(pageResultResult.getResult().getContent())) {
            SalesPlanStatScItemSDO salesPlanStatScItemSDO = pageResultResult.getResult().getContent().get(0);
            return salesPlanStatScItemSDO;
        } else {
            return null;
        }
    }

    /**
     * 根据渠道查询月度计划 渠道
     *
     * @param map
     * @return
     */
    @FunctionInvoker
    public SalesPlanStatScItemSDO pageQueryPlanScItemListGetChannelCode(String planId, ForecastOrderLineSDO map) {
        //渠道/ 部门 +货品+planId +pooltype（3）
        ForecastOrderSDO forecastOrderSDO = forecastOrderQueryRepository.load(map.getMainOrderId());
        PageQueryPlanScItemStatRequest pageQueryPlanScItemStatRequest = new PageQueryPlanScItemStatRequest();
        pageQueryPlanScItemStatRequest.setPlanId(planId);
        pageQueryPlanScItemStatRequest.setPoolType(StatPoolTypeEnum.SC_ITEM.getPoolType());
        pageQueryPlanScItemStatRequest.setScItemId(map.getScItemId());
        if (StringUtils.isNotBlank(forecastOrderSDO.getSaleChannelCode())) {
            pageQueryPlanScItemStatRequest.setBizId(forecastOrderSDO.getSaleChannelCode());
            pageQueryPlanScItemStatRequest.setBizType(SalesStatBizTypeEnum.SALES_CHANNEL.getOrganizationType());
        }
        //渠道部门
        try {
            log.error("渠道查询月度计划入参" + JSONObject.toJSONString(pageQueryPlanScItemStatRequest));
            Result<PageResult<List<SalesPlanStatScItemSDO>>> pageResultResult = salesPlanScItemStatQueryService.pageQueryPlanScItemList(pageQueryPlanScItemStatRequest);
            log.error("渠道查询月度计划出参" + JSONObject.toJSONString(pageResultResult));
            if (Objects.nonNull(pageResultResult) &&
                    Objects.nonNull(pageResultResult.getResult()) &&
                    pageResultResult.getResult().getContent().size() > 0) {
                return pageResultResult.getResult().getContent().get(0);
            }
        } catch (Exception e) {
//            e.printStackTrace();
            log.error("ERROR:SalesPlanStatScItemSDO execption:" + e.getMessage(), e);
        }
        return null;
    }

    @FunctionInvoker
    public Integer pagePlanNumber(ForecastOrderLineSDO forecastOrderLineSDO) {
        Integer taskCount = -1;//查不到数据就回复-1
        try {
            ForecastOrderSDO load = forecastOrderQueryRepository.load(forecastOrderLineSDO.getMainOrderId());
            if (Objects.nonNull(load)) {
                String planId = queryParentId(load.getOrganizationCode());
                SalesPlanLineSDO salesPlanLineSDO = pageQuerySalesPlanLineList(planId, forecastOrderLineSDO, load);
                if (Objects.nonNull(salesPlanLineSDO)) {
                    taskCount = salesPlanLineSDO.getTaskCount();
                }
            }
        } catch (Exception e) {
//            e.printStackTrace();
            log.error("查询计划差量失败", e);
        }

        return taskCount;
    }

    //对pagePlanNumber进行优化分拆为2个方法，控制方法范围，职能单一; 时间紧张控制影响面，先不做重构
    @FunctionInvoker
    public Integer pagePlanNumberV2(ForecastOrderLineSDO forecastOrderLineSDO, String planId, ForecastOrderSDO load) {
        Integer taskCount = -1;//查不到数据就回复-1
        try {
            if (Objects.nonNull(planId)) {
                SalesPlanLineSDO salesPlanLineSDO = pageQuerySalesPlanLineList(planId, forecastOrderLineSDO, load);
                if (Objects.nonNull(salesPlanLineSDO)) {
                    taskCount = salesPlanLineSDO.getTaskCount();
                }
            }
        } catch (Exception e) {
//            e.printStackTrace();
            log.error("查询计划差量失败", e);
        }

        return taskCount;
    }

    //查询合同量新接口 部门
    @FunctionInvoker
    public MonthContractAndRollingCountResponse searchContractNumberDepartment(ForecastOrderLineSDO forecastOrderLineSDO) {
        ForecastOrderSDO forecastOrderSDO = FORE_CAST_ORDER_MAP.get(forecastOrderLineSDO.getMainOrderId());
        QueryQuantityListByAddressAndScItemRequest queryRequest = new QueryQuantityListByAddressAndScItemRequest();
        queryRequest.setType(ContractStatDimensionEnum.DEPARTMENT_SC_ITEM.getCode());
        //年
        Calendar cal = Calendar.getInstance();
        Integer year = cal.get(Calendar.YEAR);
        Integer month = cal.get(Calendar.MONTH) + 1;
        queryRequest.setContractYear(String.valueOf(year));
        queryRequest.setPlanMonth(String.valueOf(month));//月
        queryRequest.setScItemIds(Lists.newArrayList(forecastOrderLineSDO.getScItemId()));
        queryRequest.setOrgSalesDepartmentCodes(Lists.newArrayList(forecastOrderSDO.getDepartmentCode()));
        log.info("查询合同量入参" + JSONObject.toJSONString(queryRequest));
        QueryQuantityListByAddressAndScItemResponse queryQuantityListByAddressAndScItemResponse = salesPlanService.queryQuantityListByAddressAndScItem(queryRequest);
        log.info("查询合同量出参" + JSONObject.toJSONString(queryRequest));
        if (null == queryQuantityListByAddressAndScItemResponse) {
            return null;
        }
        List<MonthContractAndRollingCountResponse> result = queryQuantityListByAddressAndScItemResponse.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            return result.get(0);
        }
        return null;
    }

    //查询合同量新接口 渠道
    @FunctionInvoker
    public MonthContractAndRollingCountResponse searchContractNumberChannel(ForecastOrderLineSDO forecastOrderLineSDO) {
        if (null == forecastOrderLineSDO) {
            return null;
        }
        ForecastOrderSDO forecastOrderSDO = FORE_CAST_ORDER_MAP.get(forecastOrderLineSDO.getMainOrderId());
        QueryQuantityListByAddressAndScItemRequest queryRequest = new QueryQuantityListByAddressAndScItemRequest();
        queryRequest.setType(ContractStatDimensionEnum.SALES_CHANNEL_SC_ITEM.getCode());
        //年
        Calendar cal = Calendar.getInstance();
        Integer year = cal.get(Calendar.YEAR);
        Integer month = cal.get(Calendar.MONTH) + 1;
        queryRequest.setContractYear(String.valueOf(year));
        queryRequest.setPlanMonth(String.valueOf(month));//月
        queryRequest.setScItemIds(Arrays.asList(forecastOrderLineSDO.getScItemId()));
        queryRequest.setOrgSalesChannelCodes(Arrays.asList(forecastOrderSDO.getSaleChannelCode()));//渠道
        QueryQuantityListByAddressAndScItemResponse queryQuantityListByAddressAndScItemResponse = salesPlanService.queryQuantityListByAddressAndScItem(queryRequest);
        if (null == queryQuantityListByAddressAndScItemResponse) {
            return null;
        }
        List<MonthContractAndRollingCountResponse> result = queryQuantityListByAddressAndScItemResponse.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            return result.get(0);
        }
        return null;
    }


}

